home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 1.iso / toolbox / src / exampleCode / opengl / motif / xmblur.c < prev   
C/C++ Source or Header  |  1996-11-11  |  9KB  |  305 lines

  1. /*
  2.  * Copyright (c) 1994, Silicon Graphics, Inc.
  3.  *
  4.  * Permission to use, copy, modify, distribute, and sell this software and
  5.  * its documentation for any purpose is hereby granted without fee, provided
  6.  * that the name of Silicon Graphics may not be used in any advertising or
  7.  * publicity relating to the software without the specific, prior written
  8.  * permission of Silicon Graphics.
  9.  *
  10.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
  11.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
  12.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
  13.  *
  14.  * IN NO EVENT SHALL SILICON GRAPHICS BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
  15.  * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
  16.  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF THE
  17.  * POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT OF OR IN
  18.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  19.  *
  20.  * OpenGL(TM) is a trademark of Silicon Graphics, Inc.
  21.  */
  22. /* $Revision: 1.2 $ */
  23. /* compile: cc -o xmblur xmblur.c -lGLw -lGLU -lGL -lXm -lXt -lX11 */
  24. #include <stdlib.h>
  25. #include <stdio.h>
  26. #include <Xm/Form.h>
  27. #include <Xm/Frame.h>
  28. #include <GL/GLwMDrawA.h>
  29. #include <X11/keysym.h>
  30. #include <X11/Xutil.h>
  31. #include <GL/gl.h>
  32. #include <GL/glu.h>
  33. #include <GL/glx.h>
  34.  
  35. static int      snglBuf[] =
  36. {
  37.     GLX_RGBA,
  38.     GLX_ACCUM_RED_SIZE, 8,
  39.     GLX_ACCUM_GREEN_SIZE, 8,
  40.     GLX_ACCUM_BLUE_SIZE, 8,
  41.     None
  42. };
  43.  
  44. static int      dblBuf[] =
  45. {
  46.     GLX_RGBA,
  47.     GLX_DOUBLEBUFFER,
  48.     GLX_ACCUM_RED_SIZE, 8,
  49.     GLX_ACCUM_GREEN_SIZE, 8,
  50.     GLX_ACCUM_BLUE_SIZE, 8,
  51.     None
  52. };
  53.  
  54. static String   fallbackResources[] =
  55. {
  56.     "*title: OpenGL motion blur demo",
  57.     "*glxarea*width: 300", "*glxarea*height: 300",
  58.     "*frame*x: 20", "*frame*y: 20",
  59.     "*frame*topOffset: 20", "*frame*bottomOffset: 20",
  60.     "*frame*rightOffset: 20", "*frame*leftOffset: 20",
  61.     "*frame*shadowType: SHADOW_IN",
  62.     NULL
  63. };
  64.  
  65. GLfloat         angleX = 15.0, angleY = 12.0;
  66. GLboolean       doubleBuffer = GL_TRUE;
  67.  
  68. Display        *dpy;
  69. XtAppContext    app;
  70. Widget          toplevel, form, frame, glxarea;
  71. XVisualInfo    *visinfo;
  72. GLXContext      glxcontext;
  73. XFontStruct    *xfont;
  74. int             firstChar, lastChar;
  75. GLuint          fontBase;
  76. char           *status;
  77. GLboolean       doBlur;
  78. GLUquadricObj  *quadObj;
  79.  
  80. void
  81. setBlur(GLboolean blurMode)
  82. {
  83.     doBlur = blurMode;
  84.     if (doBlur) {
  85.     status = "Blur: enabled";
  86.         glClear(GL_ACCUM_BUFFER_BIT); /* blow away accumulation contents */
  87.     } else {
  88.     status = "Blur: disabled";
  89.     }
  90. }
  91.  
  92. void
  93. drawScene(void)
  94. {
  95.     glClear(GL_COLOR_BUFFER_BIT);
  96.     /*
  97.      * Draw the wireframe cylinder.
  98.      */
  99.     glColor3f(1.0, 0.0, 0.0);
  100.     glPushMatrix();
  101.     glRotatef(angleX, 1.0, 0.0, 0.0);
  102.     glRotatef(angleY, 0.0, 1.0, 0.0);
  103.     glCallList(1);
  104.     glPopMatrix();
  105.     /*
  106.      * Use accumulation buffer for motion blurring.
  107.      */
  108.     if (doBlur) {
  109.     /*
  110.      * Be careful not to overflow the accumulation buffer; GL_RETURN is
  111.      * the only accumulation buffer operation defined to do clamping.
  112.      * Don't assume GL_MULT or GL_ACCUM clamp.
  113.      */
  114.     glAccum(GL_MULT, 0.8);
  115.     glAccum(GL_ACCUM, 0.2);
  116.     /*
  117.      * Renormalize the return by multipling the accumulation buffer
  118.      * contents by 5.
  119.      */
  120.     glAccum(GL_RETURN, 5.0);
  121.     }
  122.     /*
  123.      * Print out instructions and blur mode.
  124.      */
  125. #define HELP1 "Push 's' to step frame"
  126. #define HELP2 "Push 'b' toggles blur"
  127.     glColor3f(1.0, 1.0, 0.0);
  128.     glRasterPos2i(-14, 13);
  129.     glCallLists(sizeof(HELP1) - 1, GL_UNSIGNED_BYTE, HELP1);
  130.     glColor3f(1.0, 1.0, 0.0);
  131.     glRasterPos2i(-14, 11);
  132.     glCallLists(sizeof(HELP2) - 1, GL_UNSIGNED_BYTE, HELP2);
  133.     glColor3f(0.0, 1.0, 0.0);
  134.     glRasterPos2i(-14, -14);
  135.     glCallLists(strlen(status), GL_UNSIGNED_BYTE, (unsigned char *) status);
  136.     /*
  137.      * Swap the buffer if we are double buffering.
  138.      */
  139.     if (doubleBuffer)
  140.     GLwDrawingAreaSwapBuffers(glxarea);
  141.     /*
  142.      * Finish to ensure we aren't buffering up too much work.
  143.      */
  144.     glFinish();            
  145. }
  146.  
  147. void
  148. input_callback(Widget w, XtPointer client_data, XtPointer call)
  149. {
  150.     char            buffer[31];
  151.     KeySym          keysym;
  152.     GLwDrawingAreaCallbackStruct *call_data;
  153.     XComposeStatus  composeStatus;
  154.  
  155.     call_data = (GLwDrawingAreaCallbackStruct *) call;
  156.  
  157.     switch (call_data->event->type) {
  158.     case KeyPress:
  159.     XLookupString(&call_data->event->xkey, buffer,
  160.               30, &keysym, &composeStatus);
  161.     switch (keysym) {
  162.     case XK_Escape:
  163.         exit(0);
  164.         break;
  165.     case XK_B:
  166.     case XK_b:
  167.         setBlur(!doBlur);    /* toggle blur mode */
  168.         drawScene();
  169.         break;
  170.     case XK_S:
  171.     case XK_s:
  172.         angleX += 15.0;
  173.         angleY += 12.0;
  174.         if (angleX >= 360.0)
  175.         angleX = 0.0;
  176.         if (angleY >= 360.0)
  177.         angleY = 0.0;
  178.         drawScene();
  179.         break;
  180.     }
  181.     break;
  182.     }
  183. }
  184.  
  185. void
  186. resize_callback(Widget w, XtPointer client_data, XtPointer call)
  187. {
  188.     GLwDrawingAreaCallbackStruct *call_data;
  189.     call_data = (GLwDrawingAreaCallbackStruct *) call;
  190.  
  191.     glViewport(0, 0, call_data->width, call_data->height);
  192. }
  193.  
  194. void
  195. expose_callback(Widget w, XtPointer client_data, XtPointer call)
  196. {
  197.     GLwDrawingAreaCallbackStruct *call_data;
  198.     call_data = (GLwDrawingAreaCallbackStruct *) call;
  199.  
  200.     if (doBlur) {
  201.     /*
  202.      * Can't trust the contents of the accumulation buffer after
  203.      * an expose.  Note: this makes xmblur regenerate itself after
  204.      * an expose properly if blur is enabled.
  205.      */
  206.         glClear(GL_ACCUM_BUFFER_BIT);
  207.     }
  208.     drawScene();
  209. }
  210.  
  211. void
  212. init_callback(Widget w, XtPointer client_data, XtPointer call)
  213. {
  214.     XVisualInfo    *visinfo;
  215.  
  216.     XtVaGetValues(w, GLwNvisualInfo, &visinfo, NULL);
  217.     glxcontext = glXCreateContext(XtDisplay(w), visinfo,
  218.               /* no sharing */ 0, /* direct if possible */ GL_TRUE);
  219. }
  220.  
  221. main(int argc, char **argv)
  222. {
  223.     toplevel = XtAppInitialize(&app, "Glxwidget", NULL, 0, &argc, argv,
  224.                    fallbackResources, NULL, 0);
  225.     dpy = XtDisplay(toplevel);
  226.     form = XmCreateForm(toplevel, "form", NULL, 0);
  227.     XtManageChild(form);
  228.     frame = XmCreateFrame(form, "frame", NULL, 0);
  229.     XtVaSetValues(frame, XmNbottomAttachment, XmATTACH_FORM,
  230.       XmNtopAttachment, XmATTACH_FORM, XmNleftAttachment, XmATTACH_FORM,
  231.           XmNrightAttachment, XmATTACH_FORM, NULL);
  232.     XtManageChild(frame);
  233.     /*
  234.      * We find the XVisualInfo* we want for the GLwMDrawA widget _before_ we
  235.      * create the widget.  The alternative to this is specifying the OpenGL
  236.      * visual attributes as resources arguments when creating the widget but
  237.      * unfortunately, if a visual matching the attributes we specify does not
  238.      * exist, we get a fatal error message like:
  239.      * 
  240.      * Error: GLwMDrawingArea: requested visual not supported
  241.      * 
  242.      * By specifying exactly which XVisualInfo* we want, we avoid this problem,
  243.      * allowing us to fall back to another acceptable set of visual
  244.      * attirbutes (single buffered in this case) and print out our own more
  245.      * informative message if even the second visual selection fails.
  246.      */
  247.     visinfo = glXChooseVisual(dpy, DefaultScreen(dpy), dblBuf);
  248.     if (visinfo == NULL) {
  249.     visinfo = glXChooseVisual(dpy, DefaultScreen(dpy), snglBuf);
  250.     if (visinfo == NULL)
  251.         XtAppError(app, "no RGB visual with accumulation buffer");
  252.     doubleBuffer = GL_FALSE;
  253.     }
  254.     /*
  255.      * Load the desired font.
  256.      */
  257.     xfont = XLoadQueryFont(dpy, "9x15");
  258.     if (xfont == NULL) {
  259.     XtAppError(app, "no 9x15 font found");
  260.     }
  261.     glxarea = XtVaCreateManagedWidget("glxarea", glwMDrawingAreaWidgetClass,
  262.                       frame, GLwNvisualInfo, visinfo, NULL);
  263.     XtAddCallback(glxarea, GLwNginitCallback, init_callback, NULL);
  264.     XtAddCallback(glxarea, GLwNexposeCallback, expose_callback, NULL);
  265.     XtAddCallback(glxarea, GLwNresizeCallback, resize_callback, NULL);
  266.     XtAddCallback(glxarea, GLwNinputCallback, input_callback, NULL);
  267.     XtRealizeWidget(toplevel);
  268.     GLwDrawingAreaMakeCurrent(glxarea, glxcontext);
  269.     /*
  270.      * Make cylinder display list.
  271.      */
  272.     quadObj = gluNewQuadric();
  273.     gluQuadricDrawStyle(quadObj, GLU_LINE);
  274.     glNewList(1, GL_COMPILE);
  275.     gluCylinder(quadObj, 2.0, 5.0, 10.0, 10, 4);
  276.     glEndList();
  277.     /*
  278.      * Now the GLwNginitCallback has been called so the OpenGL context has
  279.      * been set up.  Now we can initialize the X font as a set of OpenGL
  280.      * display lists.
  281.      */
  282.     firstChar = xfont->min_char_or_byte2;
  283.     lastChar = xfont->max_char_or_byte2;
  284.     glXUseXFont(xfont->fid, firstChar, lastChar - firstChar + 1,
  285.         /* base display list of glyphs */ 2 
  286.         /* since 1 is used for the cylinder */);
  287.     glListBase(2 - firstChar);
  288.     /*
  289.      * Initialize OpenGL state.
  290.      */
  291.     glViewport(0, 0, 300, 300);    /* XXX work around Reality Engine bug */
  292.     glClearColor(0.0, 0.0, 0.0, 0.0);
  293.     glClearAccum(0.0, 0.0, 0.0, 0.0);
  294.     glMatrixMode(GL_PROJECTION);
  295.     glLoadIdentity();
  296.     glOrtho(-15.0, 15.0, -15.0, 15.0, -15.0, 15.0);
  297.     glMatrixMode(GL_MODELVIEW);
  298.     glLoadIdentity();
  299.     setBlur(GL_FALSE);
  300.     /*
  301.      * Start dispatching X events...
  302.      */
  303.     XtAppMainLoop(app);
  304. }
  305.